package org.zhq.controller;

import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.zhq.ServerResult;
import org.zhq.enums.PayMethod;
import org.zhq.enums.PaymentStatus;
import org.zhq.pojo.Orders;
import org.zhq.pojo.bo.MerchantOrdersBO;
import org.zhq.pojo.vo.PaymentInfoVO;
import org.zhq.resource.AliPayResource;
import org.zhq.resource.WXPayResource;
import org.zhq.service.IPaymentOrderService;
import org.zhq.wx.entity.PreOrderResult;
import org.zhq.wx.service.WxOrderService;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.DecimalFormat;

@RestController
@RequestMapping(value = "payment")
@Slf4j
public class PaymentController {
    private final IPaymentOrderService paymentOrderService;
    private final WXPayResource wxPayResource;
    private final WxOrderService wxOrderService;
    private final AliPayResource aliPayResource;

    private Cache<String,String> cache = CacheUtil.newTimedCache(10000);

    @Autowired
    public PaymentController(IPaymentOrderService paymentOrderService, WXPayResource wxPayResource, WxOrderService wxOrderService, AliPayResource aliPayResource) {
        this.paymentOrderService = paymentOrderService;
        this.wxPayResource = wxPayResource;
        this.wxOrderService = wxOrderService;
        this.aliPayResource = aliPayResource;
    }

    @PostMapping("/createMerchantOrder")
    public ServerResult createMerchantOrder(@RequestBody MerchantOrdersBO merchantOrdersBO){
        String merchantOrderId = merchantOrdersBO.getMerchantOrderId();             	// 订单id
        String merchantUserId = merchantOrdersBO.getMerchantUserId();     		// 用户id
        Integer amount = merchantOrdersBO.getAmount();    // 实际支付订单金额
        Integer payMethod = merchantOrdersBO.getPayMethod();          	// 支付方式
        String returnUrl = merchantOrdersBO.getReturnUrl();           	// 支付成功后的回调地址（学生自定义）

        if (StrUtil.isBlank(merchantOrderId)) {
            return ServerResult.errorMsg("参数[orderId]不能为空");
        }
        if (StrUtil.isBlank(merchantUserId)) {
            return ServerResult.errorMsg("参数[userId]不能为空");
        }
        if (amount == null || amount < 1) {
            return ServerResult.errorMsg("参数[realPayAmount]不能为空并且不能小于1");
        }
        if (payMethod == null) {
            return ServerResult.errorMsg("参数[payMethod]不能为空并且不能小于1");
        }
        if (payMethod != PayMethod.WEIXIN.type && payMethod != PayMethod.ALIPAY.type) {
            return ServerResult.errorMsg("参数[payMethod]目前只支持微信支付或支付宝支付");
        }
        if (StrUtil.isBlank(returnUrl)) {
            return ServerResult.errorMsg("参数[returnUrl]不能为空");
        }

        // 保存传来的商户订单信息
        boolean isSuccess = false;
        try {
            isSuccess = paymentOrderService.createPaymentOrder(merchantOrdersBO);
        } catch (Exception e) {
            e.printStackTrace();
            ServerResult.errorException(e.getMessage());
        }

        if (isSuccess) {
            return ServerResult.ok("商户订单创建成功！");
        } else {
            return ServerResult.errorMsg("商户订单创建失败，请重试...");
        }

    }


    /**
     * 提供给大家查询的方法，用于查询订单信息
     * @param merchantOrderId
     * @param merchantUserId
     * @return
     */
    @PostMapping("getPaymentCenterOrderInfo")
    public ServerResult getPaymentCenterOrderInfo(String merchantOrderId, String merchantUserId) {

        if (StrUtil.isBlank(merchantOrderId) || StrUtil.isBlank(merchantUserId)) {
            return ServerResult.errorMsg("查询参数不能为空！");
        }

        Orders orderInfo = paymentOrderService.queryOrderInfo(merchantUserId, merchantOrderId);

        return ServerResult.ok(orderInfo);
    }


    /**
     * @Description: 微信扫码支付页面
     */
    @PostMapping(value="/getWXPayQRCode")
    public ServerResult getWXPayQRCode(String merchantOrderId, String merchantUserId) throws Exception {


        // 根据订单ID和用户ID查询订单详情
        Orders waitPayOrder = paymentOrderService.queryOrderByStatus(merchantUserId, merchantOrderId, PaymentStatus.WAIT_PAY.type);

        // 商品描述
        String body = "天天吃货-付款用户[" + merchantUserId + "]";
        // 商户订单号
        String out_trade_no = merchantOrderId;
        // 从redis中去获得这笔订单的微信支付二维码，如果订单状态没有支付没有就放入，这样的做法防止用户频繁刷新而调用微信接口
        if (waitPayOrder != null) {
            String qrCodeUrl = cache.get(wxPayResource.getQrcodeKey() + ":" + merchantOrderId);

            if (StrUtil.isEmpty(qrCodeUrl)) {
                // 订单总金额，单位为分
//                String total_fee = String.valueOf(waitPayOrder.getAmount());
				String total_fee = "1";	// 测试用 1分钱

                // 统一下单
                PreOrderResult preOrderResult = wxOrderService.placeOrder(body, out_trade_no, total_fee);
                qrCodeUrl = preOrderResult.getCode_url();
            }

            PaymentInfoVO paymentInfoVO = new PaymentInfoVO();
            paymentInfoVO.setAmount(waitPayOrder.getAmount());
            paymentInfoVO.setMerchantOrderId(merchantOrderId);
            paymentInfoVO.setMerchantUserId(merchantUserId);
            paymentInfoVO.setQrCodeUrl(qrCodeUrl);

            cache.put(wxPayResource.getQrcodeKey() + ":" + merchantOrderId, qrCodeUrl, wxPayResource.getQrcodeExpire());

            return ServerResult.ok(paymentInfoVO);
        } else {
            return ServerResult.errorMsg("该订单不存在，或已经支付");
        }
    }


    /**
     *
     * @Description: 前往支付宝进行支付
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value="/goAlipay")
    public void goAlipay(String merchantOrderId, String merchantUserId, HttpServletResponse response) throws IOException {

        // 查询订单详情
        Orders waitPayOrder = paymentOrderService.queryOrderByStatus(merchantUserId, merchantOrderId, PaymentStatus.WAIT_PAY.type);

        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(aliPayResource.getGatewayUrl(),
                aliPayResource.getAppId(),
                aliPayResource.getMerchantPrivateKey(),
                "json",
                aliPayResource.getCharset(),
                aliPayResource.getAlipayPublicKey(),
                aliPayResource.getSignType());

        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(aliPayResource.getReturnUrl());
        alipayRequest.setNotifyUrl(aliPayResource.getNotifyUrl());

        // 商户订单号, 商户网站订单系统中唯一订单号, 必填
        String out_trade_no = merchantOrderId;
        // 付款金额, 必填 单位元
        DecimalFormat df = new DecimalFormat("#.00");
//        String total_amount = df.format(waitPayOrder.getAmount());
    	String total_amount = "0.01";	// 测试用 1分钱
        // 订单名称, 必填
        String subject = "天天吃货-付款用户[" + merchantUserId + "]";
        // 商品描述, 可空, 目前先用订单名称
        String body = subject;

        // 该笔订单允许的最晚付款时间，逾期将关闭交易。取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下，无论交易何时创建，都在0点关闭）。 该参数数值不接受小数点， 如 1.5h，可转换为 90m。
        String timeout_express = "1h";

        alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                + "\"total_amount\":\""+ total_amount +"\","
                + "\"subject\":\""+ subject +"\","
                + "\"body\":\""+ body +"\","
                + "\"timeout_express\":\""+ timeout_express +"\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
        System.out.println(JSONUtil.toJsonStr(alipayRequest));

        //若想给BizContent增加其他可选请求参数, 以增加自定义超时时间参数timeout_express来举例说明
        //alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
        //		+ "\"total_amount\":\""+ total_amount +"\","
        //		+ "\"subject\":\""+ subject +"\","
        //		+ "\"body\":\""+ body +"\","
        //		+ "\"timeout_express\":\"10m\","
        //		+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
        //请求参数可查阅【电脑网站支付的API文档-alipay.trade.page.pay-请求参数】章节

        //请求
        String alipayForm = "";
        try {
            AlipayTradePagePayResponse response1 = alipayClient.pageExecute(alipayRequest);
            if(response1.isSuccess()){
                log.info("调用成功");
            }
            alipayForm = response1.getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        log.info("支付宝支付 - 前往支付页面, alipayForm: \n{}", alipayForm);

        response.setContentType("text/html;charset=" + aliPayResource.getCharset());
        response.getWriter().write(alipayForm);//直接将完整的表单html输出到页面
        response.getWriter().flush();
        response.getWriter().close();
    }

}
